package com.platform.core.service.impl;

import com.google.common.base.Strings;
import com.platform.core.repository.SysDictGroupRepository;
import com.platform.core.repository.SysDictItemRepository;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
import com.platform.comm.dto.DtoMapper;
import com.platform.comm.enums.YnEnum;
import com.platform.core.entity.QSysDictGroup;
import com.platform.core.entity.QSysDictItem;
import com.platform.core.entity.SysDictGroup;
import com.platform.core.service.SysDictGroupService;
import com.platform.dto.DictGroupQo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.QSort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.MultiValueMap;

import java.time.LocalDateTime;
import java.util.Optional;

import static com.platform.comm.constants.GlobalConstant.BASE_REDIS_CACHE_PREFIX;

/**
 * Description: 字典组-Service实现类
 *
 * @author libin Created on 2019/7/17
 **/
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class SysDictGroupServiceImpl extends BaseEntityBizImpl<SysDictGroupRepository, SysDictGroup> implements SysDictGroupService {

    private final QSysDictGroup qSysDictGroup = QSysDictGroup.sysDictGroup;
    private final QSysDictItem qSysDictItem = QSysDictItem.sysDictItem;

    private final SysDictItemRepository sysDictItemRepository;
    private final DtoMapper dtoMapper;
//    private final RedisTemplate<String, Object> redisTemplate;

    public SysDictGroupServiceImpl(SysDictGroupRepository baseRepository,
                                   SysDictItemRepository sysDictItemRepository, DtoMapper dtoMapper) {
        super(baseRepository);
        this.sysDictItemRepository = sysDictItemRepository;
        this.dtoMapper = dtoMapper;
    }

    @Override
    public Page<DictGroupQo> queryGroups(Predicate predicate, Pageable pageable, MultiValueMap<String, String> parameters) {
        if (pageable.getSort().isUnsorted()) {
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), QSort.by(qSysDictGroup.createDate.desc()));
        }
        BooleanBuilder bool = new BooleanBuilder(predicate);
        String groupName = parameters.getFirst("groupName");
        if(StringUtils.isNoneBlank(groupName)){
            bool.and(qSysDictGroup.groupName.contains(groupName));
        }
        String groupCode = parameters.getFirst("groupCode");
        if(StringUtils.isNoneBlank(groupCode)){
            bool.and(qSysDictGroup.groupCode.contains(groupCode));
        }
        Page<SysDictGroup> page = queryByPage(builderConditions(bool, parameters, SysDictGroup.class, qSysDictGroup.getMetadata()), pageable);
        return page.map(entity -> dtoMapper.map(entity, DictGroupQo.class));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public DictGroupQo create(DictGroupQo dictGroupQo) {
        dictGroupQo.init();
        SysDictGroup entity = dtoMapper.map(dictGroupQo, SysDictGroup.class);
        saveEntity(entity);
        return dtoMapper.map(entity, DictGroupQo.class);
    }

    @CacheEvict(value = BASE_REDIS_CACHE_PREFIX + "dict", allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public DictGroupQo modify(DictGroupQo dictGroupQo) {
        SysDictGroup entity = fetchById(dictGroupQo.getId());
        dtoMapper.map(dictGroupQo, entity);
        entity.setUpdateDate(LocalDateTime.now());
        saveEntity(entity);
        return dictGroupQo;
    }

    @CacheEvict(value = BASE_REDIS_CACHE_PREFIX + "dict", allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remove(String id) {
        // 删除字典项
        sysDictItemRepository.deleteInBatch(sysDictItemRepository.findAll(qSysDictItem.groupId.eq(id)));
        // 删除字典
        repository.deleteById(id);
    }

    @Override
    public long validCode(String id, String groupCode) {
        BooleanBuilder predict = builderDictValidCondition(id);
        predict.and(qSysDictGroup.groupCode.eq(groupCode));
        return repository.count(predict);
    }

    @Override
    public long validName(String id, String groupName) {
        BooleanBuilder predict = builderDictValidCondition(id);
        predict.and(qSysDictGroup.groupName.eq(groupName));
        return repository.count(predict);
    }

    private BooleanBuilder builderDictValidCondition(String id) {
        BooleanBuilder predicate = new BooleanBuilder();
        if (!Strings.isNullOrEmpty(id)) {
            predicate.and(qSysDictGroup.id.ne(id));
        }
        return predicate;
    }

    /*private void cleanCache(String id) {
        long count = repository.count(qSysDictGroup.id.eq(id));
        if (count > 0) {
            SysDictGroup sysDictGroup = fetchById(id);
            redisTemplate.delete(BASE_REDIS_CACHE_PREFIX + "dict::" + sysDictGroup.getGroupCode());
        }
    }*/

    @Override
    public DictGroupQo queryGroupByItem(String groupItem) {
        Optional<DictGroupQo> result = repository.findOne(null,
                sql -> sql.leftJoin(qSysDictItem).on(qSysDictItem.groupId.eq(qSysDictGroup.id))
                        .where(qSysDictItem.itemCode.eq(groupItem)))
                .map(tuple -> dtoMapper.map(tuple, DictGroupQo.class));
        return result.orElse(null);
    }

    @Override
    public DictGroupQo queryGroupNameByGroupCode(String groupCode) {
        Optional<DictGroupQo> dictGroupQo = repository.findOne(qSysDictGroup.groupCode.eq(groupCode)
                .and(qSysDictGroup.delFlag.eq(YnEnum.N)))
                .map(entity -> dtoMapper.map(entity, DictGroupQo.class));
        return dictGroupQo.orElse(null);
    }
}
